//
//  FFMpegKitTool.m
//  FFMpegKitDemo
//
//  Created by ilongge on 2023/8/16.
//

#import "FFMpegKitTool.h"
#import <ffmpegkit/ffmpegkit.h>
#import <libavcodec/avcodec.h>
#import <libavcodec/avcodec.h>
#import <libavdevice/avdevice.h>
#import <libavfilter/avfilter.h>
#import <libavformat/avformat.h>
#import <libswscale/swscale.h>
#import <libswresample/swresample.h>
#import <libavutil/ffversion.h>
@implementation FFMpegKitTool

+ (NSString *)av_dump_format:(AVFormatContext *)formatContext streamIndex:(int)streamIndex url:(NSString *)url is_output:(BOOL)is_output
{
    NSMutableString *info_string = [NSMutableString string];
    [info_string appendString:[FFMpegKitTool showFFmpegInfo]];
    uint8_t *printed = formatContext->nb_streams ? av_mallocz(formatContext->nb_streams) : NULL;
    if (formatContext->nb_streams && printed == NULL) {
        return nil;
    }
    [info_string appendFormat:@"%@ #%d, %s %@ '%@':\n",
     is_output?@"Output":@"Input",
     streamIndex,
     is_output?formatContext->oformat->name:formatContext->iformat->name,
     is_output?@"to":@"from",
     url];
    
    NSString *metadata = [FFMpegKitTool av_dump_metadata:formatContext->metadata indent:@"  "];
    [info_string appendString:metadata];
    if (is_output == NO) {
        [info_string appendString:@"  Duration: "];
        if (formatContext->duration != AV_NOPTS_VALUE) {
            NSString *format_duration = [FFMpegKitTool av_format_duration:formatContext->duration];
            [info_string appendString:format_duration];
        }
        else{
            [info_string appendString:@"N/A"];
        }
        if (formatContext->start_time != AV_NOPTS_VALUE) {
            [info_string appendString:@", start:"];
            long secs, us;
            secs = llabs(formatContext->start_time / AV_TIME_BASE);
            us   = llabs(formatContext->start_time % AV_TIME_BASE);
            [info_string appendFormat:@"%s%ld.%06d",formatContext->start_time >= 0 ? "" : "-", secs, (int) av_rescale(us, 1000000, AV_TIME_BASE)];
        }
        [info_string appendString:@", bitrate: "];
        if (formatContext->bit_rate) {
            [info_string appendFormat:@"%"PRId64" kb/s", formatContext->bit_rate / 1000];
        }
        else{
            [info_string appendString:@"N/A"];
        }
        [info_string appendString:@"\n"];
    }
    if (formatContext->nb_chapters) {
        [info_string appendString:@"  Chapters:\n"];
    }
    for (int i = 0; i < formatContext->nb_chapters; i++) {
        const AVChapter *chapter = formatContext->chapters[i];
        [info_string appendFormat:@"    Chapter #%d:%d: ", streamIndex, i];
        [info_string appendFormat:@"start %f, ", chapter->start * av_q2d(chapter->time_base)];
        [info_string appendFormat:@"end %f\n", chapter->end * av_q2d(chapter->time_base)];
        NSString *metadata = [FFMpegKitTool av_dump_metadata:chapter->metadata indent:@"      "];
        [info_string appendString:metadata];
    }
    
    if (formatContext->nb_programs) {
        int j, k, total = 0;
        for (j = 0; j < formatContext->nb_programs; j++) {
            const AVProgram *program = formatContext->programs[j];
            const AVDictionaryEntry *name = av_dict_get(program->metadata,
                                                        "name", NULL, 0);
            [info_string appendFormat:@"  Program %d %s\n", program->id,
             name ? name->value : ""];
            NSString *metadata = [FFMpegKitTool av_dump_metadata:program->metadata indent:@"    "];
            [info_string appendString:metadata];
            for (k = 0; k < program->nb_stream_indexes; k++) {
                NSString *streamInfoString = [FFMpegKitTool av_dump_stream_format:formatContext stream_index:program->stream_index[k] streamIndex:streamIndex is_output:is_output];
                [info_string appendString:streamInfoString];
                printed[program->stream_index[k]] = 1;
            }
            total += program->nb_stream_indexes;
        }
        if (total < formatContext->nb_streams) {
            [info_string appendFormat:@"  No Program\n"];
        }
    }
    for (int i = 0; i < formatContext->nb_streams; i++) {
        if (!printed[i]) {
            NSString *streamInfoString = [FFMpegKitTool av_dump_stream_format:formatContext stream_index:i streamIndex:streamIndex is_output:is_output];
            [info_string appendString:streamInfoString];
        }
    }
    av_free(printed);
    return info_string;
}

+ (NSString *)showFFmpegInfo
{
    NSMutableString *info_string = [NSMutableString string];
    NSString *buildDate = [FFmpegKitConfig getBuildDate];
    [info_string appendFormat:@"ffmpeg version %s Copyright (c) 2000-%@ the FFmpeg developers\n", FFMPEG_VERSION, [buildDate substringToIndex:4]];
    [info_string appendString:@"\tconfiguration: "];
    [info_string appendFormat:@"%s\n", avformat_configuration()];
    NSString *lib_info_string = [FFMpegKitTool showAllLibInfo];
    [info_string appendString:lib_info_string];
    [info_string appendString:@"Hyper fast Audio and Video encoder\n\n"];
    return info_string.copy;
}

+ (NSString *)showAllLibInfo {
    NSMutableString *info_string = [NSMutableString string];
    int ver_major,ver_minor,ver_micro;
    unsigned version = avutil_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libavutil".UTF8String, ver_major, ver_minor, ver_micro];
    version = avcodec_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libavcodec".UTF8String, ver_major, ver_minor, ver_micro];
    version = avformat_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libavformat".UTF8String, ver_major, ver_minor, ver_micro];
    version = avdevice_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libavdevice".UTF8String, ver_major, ver_minor, ver_micro];
    version = avfilter_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libavfilter".UTF8String, ver_major, ver_minor, ver_micro];
    version = swscale_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libswscale".UTF8String, ver_major, ver_minor, ver_micro];
    version = swresample_version();
    ver_major = (version>>16)&0xff;
    ver_minor = (version>>8)&0xff;
    ver_micro = (version)&0xff;
    [info_string appendFormat:@"\t%-16s %3d.%2d.%3d\n", @"libswresample".UTF8String, ver_major, ver_minor, ver_micro];
    return info_string;
}
+ (NSString *)av_dump_stream_format:(AVFormatContext *)formatContext stream_index:(int)stream_index streamIndex:(int)streamIndex is_output:(BOOL)is_output
{
    NSMutableString *stream_info_string = [NSMutableString string];
    char buf[256];
    int flags = (is_output ? formatContext->oformat->flags : formatContext->iformat->flags);
    const AVStream *st = formatContext->streams[stream_index];
    const AVDictionaryEntry *lang = av_dict_get(st->metadata, "language", NULL, 0);
    const uint8_t *separator = formatContext->dump_separator;
    AVCodecContext *avctx;
    int ret;
    
    avctx = avcodec_alloc_context3(NULL);
    if (!avctx)
        return nil;
    
    ret = avcodec_parameters_to_context(avctx, st->codecpar);
    if (ret < 0) {
        avcodec_free_context(&avctx);
        return nil;
    }
    avctx->properties   = avctx->properties;
    avctx->codec        = avctx->codec;
    avctx->qmin         = avctx->qmin;
    avctx->qmax         = avctx->qmax;
    avctx->coded_width  = avctx->coded_width;
    avctx->coded_height = avctx->coded_height;
    
    if (separator)
        av_opt_set(avctx, "dump_separator", (char *)separator, 0);
    avcodec_string(buf, sizeof(buf), avctx, is_output);
    avcodec_free_context(&avctx);
    [stream_info_string appendFormat:@"%@",@""];
    [stream_info_string appendFormat:@"  Stream #%d:%d", streamIndex, stream_index];
    
    if (flags & AVFMT_SHOW_IDS)
        [stream_info_string appendFormat:@"[0x%x]", st->id];
    if (lang)
        [stream_info_string appendFormat:@"(%s)", lang->value];
    [stream_info_string appendFormat:@": %s", buf];
    
    if (st->sample_aspect_ratio.num &&
        av_cmp_q(st->sample_aspect_ratio, st->codecpar->sample_aspect_ratio)) {
        AVRational display_aspect_ratio;
        av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
                  st->codecpar->width  * (int64_t)st->sample_aspect_ratio.num,
                  st->codecpar->height * (int64_t)st->sample_aspect_ratio.den,
                  1024 * 1024);
        [stream_info_string appendFormat:@", SAR %d:%d DAR %d:%d",
         st->sample_aspect_ratio.num, st->sample_aspect_ratio.den,
         display_aspect_ratio.num, display_aspect_ratio.den];
    }
    
    if (st->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
        int fps = st->avg_frame_rate.den && st->avg_frame_rate.num;
        int tbr = st->r_frame_rate.den && st->r_frame_rate.num;
        int tbn = st->time_base.den && st->time_base.num;
        
        if (fps || tbr || tbn)
            [stream_info_string appendFormat:@"%s", separator];
        
        if (fps) {
            NSString *string = [FFMpegKitTool av_print_fps:av_q2d(st->avg_frame_rate) postfix: tbr || tbn ? "fps, " : "fps"];
            [stream_info_string appendString:string];
        }
        if (tbr) {
            NSString *string = [FFMpegKitTool av_print_fps:av_q2d(st->r_frame_rate) postfix: tbn ? "tbr, " : "tbr"];
            [stream_info_string appendString:string];
        }
        if (tbn) {
            NSString *string = [FFMpegKitTool av_print_fps:1 / av_q2d(st->time_base) postfix: "tbn"];
            [stream_info_string appendString:string];
        }
    }
    
    if (st->disposition & AV_DISPOSITION_DEFAULT)
        [stream_info_string appendFormat:@" (default)"];
    if (st->disposition & AV_DISPOSITION_DUB)
        [stream_info_string appendFormat:@" (dub)"];
    if (st->disposition & AV_DISPOSITION_ORIGINAL)
        [stream_info_string appendFormat:@" (original)"];
    if (st->disposition & AV_DISPOSITION_COMMENT)
        [stream_info_string appendFormat:@" (comment)"];
    if (st->disposition & AV_DISPOSITION_LYRICS)
        [stream_info_string appendFormat:@" (lyrics)"];
    if (st->disposition & AV_DISPOSITION_KARAOKE)
        [stream_info_string appendFormat:@" (karaoke)"];
    if (st->disposition & AV_DISPOSITION_FORCED)
        [stream_info_string appendFormat:@" (forced)"];
    if (st->disposition & AV_DISPOSITION_HEARING_IMPAIRED)
        [stream_info_string appendFormat:@" (hearing impaired)"];
    if (st->disposition & AV_DISPOSITION_VISUAL_IMPAIRED)
        [stream_info_string appendFormat:@" (visual impaired)"];
    if (st->disposition & AV_DISPOSITION_CLEAN_EFFECTS)
        [stream_info_string appendFormat:@" (clean effects)"];
    if (st->disposition & AV_DISPOSITION_ATTACHED_PIC)
        [stream_info_string appendFormat:@" (attached pic)"];
    if (st->disposition & AV_DISPOSITION_TIMED_THUMBNAILS)
        [stream_info_string appendFormat:@" (timed thumbnails)"];
    if (st->disposition & AV_DISPOSITION_CAPTIONS)
        [stream_info_string appendFormat:@" (captions)"];
    if (st->disposition & AV_DISPOSITION_DESCRIPTIONS)
        [stream_info_string appendFormat:@" (descriptions)"];
    if (st->disposition & AV_DISPOSITION_METADATA)
        [stream_info_string appendFormat:@" (metadata)"];
    if (st->disposition & AV_DISPOSITION_DEPENDENT)
        [stream_info_string appendFormat:@" (dependent)"];
    if (st->disposition & AV_DISPOSITION_STILL_IMAGE)
        [stream_info_string appendFormat:@" (still image)"];
    if (st->disposition & AV_DISPOSITION_NON_DIEGETIC)
        [stream_info_string appendFormat:@" (non-diegetic)"];
    [stream_info_string appendString:@"\n"];
    NSString *metadata_string = [FFMpegKitTool av_dump_metadata:st->metadata indent:@"    "];
    [stream_info_string appendString:metadata_string];
    return stream_info_string;
}

+(NSString *)av_print_fps:(double)d postfix:(const char *)postfix
{
    NSString *string = @"";
    uint64_t v = lrintf(d * 100);
    if (!v)
        string = [NSString stringWithFormat:@"%1.4f %s", d, postfix];
    else if (v % 100)
        string = [NSString stringWithFormat:@"%3.2f %s", d, postfix];
    else if (v % (100 * 1000))
        string = [NSString stringWithFormat:@"%1.0f %s", d, postfix];
    else
        string = [NSString stringWithFormat:@"%1.0fk %s", d / 1000, postfix];
    return string;
}

+ (NSString *)av_format_duration:(int64_t)duration
{
    int seconds = (int)(duration / 1000 / 1000);
    int mircoSeconds = (int)(duration / 1000 % 1000);
    int hour = seconds / 3600;
    int mins = seconds % 3600 / 60;
    int second = seconds % 60;
    NSString *format = [NSString stringWithFormat:@"%02d:%02d:%02d.%03d", hour, mins, second, mircoSeconds];
    return format;
}

+ (NSString *)av_dump_metadata:(AVDictionary *)metadata indent:(NSString *)indent
{
    NSMutableString *metadata_string = [NSMutableString string];
    [metadata_string appendFormat:@"%@Metadata:\n", indent];
    if (metadata && (av_dict_count(metadata) == 1 && av_dict_get(metadata, "language", NULL, 0)) == NO) {
        const AVDictionaryEntry *tag = NULL;
        while ((tag = av_dict_get(metadata, "", tag, AV_DICT_IGNORE_SUFFIX)))
            if (strcmp("language", tag->key)) {
                const char *p = tag->value;
                [metadata_string appendFormat:@"%@  %-20s:  ", indent, tag->key];
                while (*p) {
                    char tmp[256];
                    size_t len = strcspn(p, "\x8\xa\xb\xc\xd");
                    av_strlcpy(tmp, p, FFMIN(sizeof(tmp), len+1));
                    [metadata_string appendFormat:@"%s",tmp];
                    p += len;
                    if (*p == 0xd) [metadata_string appendString:@" "];
                    if (*p == 0xa) [metadata_string appendFormat:@"\n%@  %-20s:  ", indent, @"".UTF8String];
                    if (*p) p++;
                }
                [metadata_string appendString:@"\n"];
            }
    }
    return metadata_string.copy;
}

+ (NSString *)av_sample_format_string:(enum AVSampleFormat)sampleFormat
{
    NSString *sample_format_string = @"";
    switch (sampleFormat) {
        case AV_SAMPLE_FMT_NONE:
            sample_format_string = @"AV_SAMPLE_FMT_NONE";
            break;
        case AV_SAMPLE_FMT_U8:
            sample_format_string = @"AV_SAMPLE_FMT_U8";
            break;
        case AV_SAMPLE_FMT_S16:
            sample_format_string = @"AV_SAMPLE_FMT_S16";
            break;
        case AV_SAMPLE_FMT_S32:
            sample_format_string = @"AV_SAMPLE_FMT_S32";
            break;
        case AV_SAMPLE_FMT_FLT:
            sample_format_string = @"AV_SAMPLE_FMT_FLT";
            break;
        case AV_SAMPLE_FMT_DBL:
            sample_format_string = @"AV_SAMPLE_FMT_DBL";
            break;
        case AV_SAMPLE_FMT_U8P:
            sample_format_string = @"AV_SAMPLE_FMT_U8P";
            break;
        case AV_SAMPLE_FMT_S16P:
            sample_format_string = @"AV_SAMPLE_FMT_S16P";
            break;
        case AV_SAMPLE_FMT_S32P:
            sample_format_string = @"AV_SAMPLE_FMT_S32P";
            break;
        case AV_SAMPLE_FMT_FLTP:
            sample_format_string = @"AV_SAMPLE_FMT_FLTP";
            break;
        case AV_SAMPLE_FMT_DBLP:
            sample_format_string = @"AV_SAMPLE_FMT_DBLP";
            break;
        case AV_SAMPLE_FMT_S64:
            sample_format_string = @"AV_SAMPLE_FMT_S64";
            break;
        case AV_SAMPLE_FMT_S64P:
            sample_format_string = @"AV_SAMPLE_FMT_S64P";
            break;
        case AV_SAMPLE_FMT_NB:
            sample_format_string = @"AV_SAMPLE_FMT_NB";
            break;
    }
    return sample_format_string;
}

+ (NSString *)av_pixel_format_string:(enum AVPixelFormat)pixelFormat
{
    NSString *pixel_format_string = @"";
    switch (pixelFormat) {
        case AV_PIX_FMT_NONE: pixel_format_string = @"AV_PIX_FMT_NONE"; break;
        case AV_PIX_FMT_YUV420P: pixel_format_string = @"AV_PIX_FMT_YUV420P"; break;
        case AV_PIX_FMT_YUYV422: pixel_format_string = @"AV_PIX_FMT_YUYV422"; break;
        case AV_PIX_FMT_RGB24: pixel_format_string = @"AV_PIX_FMT_RGB24"; break;
        case AV_PIX_FMT_BGR24: pixel_format_string = @"AV_PIX_FMT_BGR24"; break;
        case AV_PIX_FMT_YUV422P: pixel_format_string = @"AV_PIX_FMT_YUV422P"; break;
        case AV_PIX_FMT_YUV444P: pixel_format_string = @"AV_PIX_FMT_YUV444P"; break;
        case AV_PIX_FMT_YUV410P: pixel_format_string = @"AV_PIX_FMT_YUV410P"; break;
        case AV_PIX_FMT_YUV411P: pixel_format_string = @"AV_PIX_FMT_YUV411P"; break;
        case AV_PIX_FMT_GRAY8: pixel_format_string = @"AV_PIX_FMT_GRAY8"; break;
        case AV_PIX_FMT_MONOWHITE: pixel_format_string = @"AV_PIX_FMT_MONOWHITE"; break;
        case AV_PIX_FMT_MONOBLACK: pixel_format_string = @"AV_PIX_FMT_MONOBLACK"; break;
        case AV_PIX_FMT_PAL8: pixel_format_string = @"AV_PIX_FMT_PAL8"; break;
        case AV_PIX_FMT_YUVJ420P: pixel_format_string = @"AV_PIX_FMT_YUVJ420P"; break;
        case AV_PIX_FMT_YUVJ422P: pixel_format_string = @"AV_PIX_FMT_YUVJ422P"; break;
        case AV_PIX_FMT_YUVJ444P: pixel_format_string = @"AV_PIX_FMT_YUVJ444P"; break;
        case AV_PIX_FMT_UYVY422: pixel_format_string = @"AV_PIX_FMT_UYVY422"; break;
        case AV_PIX_FMT_UYYVYY411: pixel_format_string = @"AV_PIX_FMT_UYYVYY411"; break;
        case AV_PIX_FMT_BGR8: pixel_format_string = @"AV_PIX_FMT_BGR8"; break;
        case AV_PIX_FMT_BGR4: pixel_format_string = @"AV_PIX_FMT_BGR4"; break;
        case AV_PIX_FMT_BGR4_BYTE: pixel_format_string = @"AV_PIX_FMT_BGR4_BYTE"; break;
        case AV_PIX_FMT_RGB8: pixel_format_string = @"AV_PIX_FMT_RGB8"; break;
        case AV_PIX_FMT_RGB4: pixel_format_string = @"AV_PIX_FMT_RGB4"; break;
        case AV_PIX_FMT_RGB4_BYTE: pixel_format_string = @"AV_PIX_FMT_RGB4_BYTE"; break;
        case AV_PIX_FMT_NV12: pixel_format_string = @"AV_PIX_FMT_NV12"; break;
        case AV_PIX_FMT_NV21: pixel_format_string = @"AV_PIX_FMT_NV21"; break;
        case AV_PIX_FMT_ARGB: pixel_format_string = @"AV_PIX_FMT_ARGB"; break;
        case AV_PIX_FMT_RGBA: pixel_format_string = @"AV_PIX_FMT_RGBA"; break;
        case AV_PIX_FMT_ABGR: pixel_format_string = @"AV_PIX_FMT_ABGR"; break;
        case AV_PIX_FMT_BGRA: pixel_format_string = @"AV_PIX_FMT_BGRA"; break;
        case AV_PIX_FMT_GRAY16BE: pixel_format_string = @"AV_PIX_FMT_GRAY16BE"; break;
        case AV_PIX_FMT_GRAY16LE: pixel_format_string = @"AV_PIX_FMT_GRAY16LE"; break;
        case AV_PIX_FMT_YUV440P: pixel_format_string = @"AV_PIX_FMT_YUV440P"; break;
        case AV_PIX_FMT_YUVJ440P: pixel_format_string = @"AV_PIX_FMT_YUVJ440P"; break;
        case AV_PIX_FMT_YUVA420P: pixel_format_string = @"AV_PIX_FMT_YUVA420P"; break;
        case AV_PIX_FMT_RGB48BE: pixel_format_string = @"AV_PIX_FMT_RGB48BE"; break;
        case AV_PIX_FMT_RGB48LE: pixel_format_string = @"AV_PIX_FMT_RGB48LE"; break;
        case AV_PIX_FMT_RGB565BE: pixel_format_string = @"AV_PIX_FMT_RGB565BE"; break;
        case AV_PIX_FMT_RGB565LE: pixel_format_string = @"AV_PIX_FMT_RGB565LE"; break;
        case AV_PIX_FMT_RGB555BE: pixel_format_string = @"AV_PIX_FMT_RGB555BE"; break;
        case AV_PIX_FMT_RGB555LE: pixel_format_string = @"AV_PIX_FMT_RGB555LE"; break;
        case AV_PIX_FMT_BGR565BE: pixel_format_string = @"AV_PIX_FMT_BGR565BE"; break;
        case AV_PIX_FMT_BGR565LE: pixel_format_string = @"AV_PIX_FMT_BGR565LE"; break;
        case AV_PIX_FMT_BGR555BE: pixel_format_string = @"AV_PIX_FMT_BGR555BE"; break;
        case AV_PIX_FMT_BGR555LE: pixel_format_string = @"AV_PIX_FMT_BGR555LE"; break;
        case AV_PIX_FMT_VAAPI: pixel_format_string = @"AV_PIX_FMT_VAAPI"; break;
        case AV_PIX_FMT_YUV420P16LE: pixel_format_string = @"AV_PIX_FMT_YUV420P16LE"; break;
        case AV_PIX_FMT_YUV420P16BE: pixel_format_string = @"AV_PIX_FMT_YUV420P16BE"; break;
        case AV_PIX_FMT_YUV422P16LE: pixel_format_string = @"AV_PIX_FMT_YUV422P16LE"; break;
        case AV_PIX_FMT_YUV422P16BE: pixel_format_string = @"AV_PIX_FMT_YUV422P16BE"; break;
        case AV_PIX_FMT_YUV444P16LE: pixel_format_string = @"AV_PIX_FMT_YUV444P16LE"; break;
        case AV_PIX_FMT_YUV444P16BE: pixel_format_string = @"AV_PIX_FMT_YUV444P16BE"; break;
        case AV_PIX_FMT_DXVA2_VLD: pixel_format_string = @"AV_PIX_FMT_DXVA2_VLD"; break;
        case AV_PIX_FMT_RGB444LE: pixel_format_string = @"AV_PIX_FMT_RGB444LE"; break;
        case AV_PIX_FMT_RGB444BE: pixel_format_string = @"AV_PIX_FMT_RGB444BE"; break;
        case AV_PIX_FMT_BGR444LE: pixel_format_string = @"AV_PIX_FMT_BGR444LE"; break;
        case AV_PIX_FMT_BGR444BE: pixel_format_string = @"AV_PIX_FMT_BGR444BE"; break;
        case AV_PIX_FMT_YA8: pixel_format_string = @"AV_PIX_FMT_YA8"; break;
        case AV_PIX_FMT_BGR48BE: pixel_format_string = @"AV_PIX_FMT_BGR48BE"; break;
        case AV_PIX_FMT_BGR48LE: pixel_format_string = @"AV_PIX_FMT_BGR48LE"; break;
        case AV_PIX_FMT_YUV420P9BE: pixel_format_string = @"AV_PIX_FMT_YUV420P9BE"; break;
        case AV_PIX_FMT_YUV420P9LE: pixel_format_string = @"AV_PIX_FMT_YUV420P9LE"; break;
        case AV_PIX_FMT_YUV420P10BE: pixel_format_string = @"AV_PIX_FMT_YUV420P10BE"; break;
        case AV_PIX_FMT_YUV420P10LE: pixel_format_string = @"AV_PIX_FMT_YUV420P10LE"; break;
        case AV_PIX_FMT_YUV422P10BE: pixel_format_string = @"AV_PIX_FMT_YUV422P10BE"; break;
        case AV_PIX_FMT_YUV422P10LE: pixel_format_string = @"AV_PIX_FMT_YUV422P10LE"; break;
        case AV_PIX_FMT_YUV444P9BE: pixel_format_string = @"AV_PIX_FMT_YUV444P9BE"; break;
        case AV_PIX_FMT_YUV444P9LE: pixel_format_string = @"AV_PIX_FMT_YUV444P9LE"; break;
        case AV_PIX_FMT_YUV444P10BE: pixel_format_string = @"AV_PIX_FMT_YUV444P10BE"; break;
        case AV_PIX_FMT_YUV444P10LE: pixel_format_string = @"AV_PIX_FMT_YUV444P10LE"; break;
        case AV_PIX_FMT_YUV422P9BE: pixel_format_string = @"AV_PIX_FMT_YUV422P9BE"; break;
        case AV_PIX_FMT_YUV422P9LE: pixel_format_string = @"AV_PIX_FMT_YUV422P9LE"; break;
        case AV_PIX_FMT_GBRP: pixel_format_string = @"AV_PIX_FMT_GBRP"; break;
        case AV_PIX_FMT_GBRP9BE: pixel_format_string = @"AV_PIX_FMT_GBRP9BE"; break;
        case AV_PIX_FMT_GBRP9LE: pixel_format_string = @"AV_PIX_FMT_GBRP9LE"; break;
        case AV_PIX_FMT_GBRP10BE: pixel_format_string = @"AV_PIX_FMT_GBRP10BE"; break;
        case AV_PIX_FMT_GBRP10LE: pixel_format_string = @"AV_PIX_FMT_GBRP10LE"; break;
        case AV_PIX_FMT_GBRP16BE: pixel_format_string = @"AV_PIX_FMT_GBRP16BE"; break;
        case AV_PIX_FMT_GBRP16LE: pixel_format_string = @"AV_PIX_FMT_GBRP16LE"; break;
        case AV_PIX_FMT_YUVA422P: pixel_format_string = @"AV_PIX_FMT_YUVA422P"; break;
        case AV_PIX_FMT_YUVA444P: pixel_format_string = @"AV_PIX_FMT_YUVA444P"; break;
        case AV_PIX_FMT_YUVA420P9BE: pixel_format_string = @"AV_PIX_FMT_YUVA420P9BE"; break;
        case AV_PIX_FMT_YUVA420P9LE: pixel_format_string = @"AV_PIX_FMT_YUVA420P9LE"; break;
        case AV_PIX_FMT_YUVA422P9BE: pixel_format_string = @"AV_PIX_FMT_YUVA422P9BE"; break;
        case AV_PIX_FMT_YUVA422P9LE: pixel_format_string = @"AV_PIX_FMT_YUVA422P9LE"; break;
        case AV_PIX_FMT_YUVA444P9BE: pixel_format_string = @"AV_PIX_FMT_YUVA444P9BE"; break;
        case AV_PIX_FMT_YUVA444P9LE: pixel_format_string = @"AV_PIX_FMT_YUVA444P9LE"; break;
        case AV_PIX_FMT_YUVA420P10BE: pixel_format_string = @"AV_PIX_FMT_YUVA420P10BE"; break;
        case AV_PIX_FMT_YUVA420P10LE: pixel_format_string = @"AV_PIX_FMT_YUVA420P10LE"; break;
        case AV_PIX_FMT_YUVA422P10BE: pixel_format_string = @"AV_PIX_FMT_YUVA422P10BE"; break;
        case AV_PIX_FMT_YUVA422P10LE: pixel_format_string = @"AV_PIX_FMT_YUVA422P10LE"; break;
        case AV_PIX_FMT_YUVA444P10BE: pixel_format_string = @"AV_PIX_FMT_YUVA444P10BE"; break;
        case AV_PIX_FMT_YUVA444P10LE: pixel_format_string = @"AV_PIX_FMT_YUVA444P10LE"; break;
        case AV_PIX_FMT_YUVA420P16BE: pixel_format_string = @"AV_PIX_FMT_YUVA420P16BE"; break;
        case AV_PIX_FMT_YUVA420P16LE: pixel_format_string = @"AV_PIX_FMT_YUVA420P16LE"; break;
        case AV_PIX_FMT_YUVA422P16BE: pixel_format_string = @"AV_PIX_FMT_YUVA422P16BE"; break;
        case AV_PIX_FMT_YUVA422P16LE: pixel_format_string = @"AV_PIX_FMT_YUVA422P16LE"; break;
        case AV_PIX_FMT_YUVA444P16BE: pixel_format_string = @"AV_PIX_FMT_YUVA444P16BE"; break;
        case AV_PIX_FMT_YUVA444P16LE: pixel_format_string = @"AV_PIX_FMT_YUVA444P16LE"; break;
        case AV_PIX_FMT_VDPAU: pixel_format_string = @"AV_PIX_FMT_VDPAU"; break;
        case AV_PIX_FMT_XYZ12LE: pixel_format_string = @"AV_PIX_FMT_XYZ12LE"; break;
        case AV_PIX_FMT_XYZ12BE: pixel_format_string = @"AV_PIX_FMT_XYZ12BE"; break;
        case AV_PIX_FMT_NV16: pixel_format_string = @"AV_PIX_FMT_NV16"; break;
        case AV_PIX_FMT_NV20LE: pixel_format_string = @"AV_PIX_FMT_NV20LE"; break;
        case AV_PIX_FMT_NV20BE: pixel_format_string = @"AV_PIX_FMT_NV20BE"; break;
        case AV_PIX_FMT_RGBA64BE: pixel_format_string = @"AV_PIX_FMT_RGBA64BE"; break;
        case AV_PIX_FMT_RGBA64LE: pixel_format_string = @"AV_PIX_FMT_RGBA64LE"; break;
        case AV_PIX_FMT_BGRA64BE: pixel_format_string = @"AV_PIX_FMT_BGRA64BE"; break;
        case AV_PIX_FMT_BGRA64LE: pixel_format_string = @"AV_PIX_FMT_BGRA64LE"; break;
        case AV_PIX_FMT_YVYU422: pixel_format_string = @"AV_PIX_FMT_YVYU422"; break;
        case AV_PIX_FMT_YA16BE: pixel_format_string = @"AV_PIX_FMT_YA16BE"; break;
        case AV_PIX_FMT_YA16LE: pixel_format_string = @"AV_PIX_FMT_YA16LE"; break;
        case AV_PIX_FMT_GBRAP: pixel_format_string = @"AV_PIX_FMT_GBRAP"; break;
        case AV_PIX_FMT_GBRAP16BE: pixel_format_string = @"AV_PIX_FMT_GBRAP16BE"; break;
        case AV_PIX_FMT_GBRAP16LE: pixel_format_string = @"AV_PIX_FMT_GBRAP16LE"; break;
        case AV_PIX_FMT_QSV: pixel_format_string = @"AV_PIX_FMT_QSV"; break;
        case AV_PIX_FMT_MMAL: pixel_format_string = @"AV_PIX_FMT_MMAL"; break;
        case AV_PIX_FMT_D3D11VA_VLD: pixel_format_string = @"AV_PIX_FMT_D3D11VA_VLD"; break;
        case AV_PIX_FMT_CUDA: pixel_format_string = @"AV_PIX_FMT_CUDA"; break;
        case AV_PIX_FMT_0RGB: pixel_format_string = @"AV_PIX_FMT_0RGB"; break;
        case AV_PIX_FMT_RGB0: pixel_format_string = @"AV_PIX_FMT_RGB0"; break;
        case AV_PIX_FMT_0BGR: pixel_format_string = @"AV_PIX_FMT_0BGR"; break;
        case AV_PIX_FMT_BGR0: pixel_format_string = @"AV_PIX_FMT_BGR0"; break;
        case AV_PIX_FMT_YUV420P12BE: pixel_format_string = @"AV_PIX_FMT_YUV420P12BE"; break;
        case AV_PIX_FMT_YUV420P12LE: pixel_format_string = @"AV_PIX_FMT_YUV420P12LE"; break;
        case AV_PIX_FMT_YUV420P14BE: pixel_format_string = @"AV_PIX_FMT_YUV420P14BE"; break;
        case AV_PIX_FMT_YUV420P14LE: pixel_format_string = @"AV_PIX_FMT_YUV420P14LE"; break;
        case AV_PIX_FMT_YUV422P12BE: pixel_format_string = @"AV_PIX_FMT_YUV422P12BE"; break;
        case AV_PIX_FMT_YUV422P12LE: pixel_format_string = @"AV_PIX_FMT_YUV422P12LE"; break;
        case AV_PIX_FMT_YUV422P14BE: pixel_format_string = @"AV_PIX_FMT_YUV422P14BE"; break;
        case AV_PIX_FMT_YUV422P14LE: pixel_format_string = @"AV_PIX_FMT_YUV422P14LE"; break;
        case AV_PIX_FMT_YUV444P12BE: pixel_format_string = @"AV_PIX_FMT_YUV444P12BE"; break;
        case AV_PIX_FMT_YUV444P12LE: pixel_format_string = @"AV_PIX_FMT_YUV444P12LE"; break;
        case AV_PIX_FMT_YUV444P14BE: pixel_format_string = @"AV_PIX_FMT_YUV444P14BE"; break;
        case AV_PIX_FMT_YUV444P14LE: pixel_format_string = @"AV_PIX_FMT_YUV444P14LE"; break;
        case AV_PIX_FMT_GBRP12BE: pixel_format_string = @"AV_PIX_FMT_GBRP12BE"; break;
        case AV_PIX_FMT_GBRP12LE: pixel_format_string = @"AV_PIX_FMT_GBRP12LE"; break;
        case AV_PIX_FMT_GBRP14BE: pixel_format_string = @"AV_PIX_FMT_GBRP14BE"; break;
        case AV_PIX_FMT_GBRP14LE: pixel_format_string = @"AV_PIX_FMT_GBRP14LE"; break;
        case AV_PIX_FMT_YUVJ411P: pixel_format_string = @"AV_PIX_FMT_YUVJ411P"; break;
        case AV_PIX_FMT_BAYER_BGGR8: pixel_format_string = @"AV_PIX_FMT_BAYER_BGGR8"; break;
        case AV_PIX_FMT_BAYER_RGGB8: pixel_format_string = @"AV_PIX_FMT_BAYER_RGGB8"; break;
        case AV_PIX_FMT_BAYER_GBRG8: pixel_format_string = @"AV_PIX_FMT_BAYER_GBRG8"; break;
        case AV_PIX_FMT_BAYER_GRBG8: pixel_format_string = @"AV_PIX_FMT_BAYER_GRBG8"; break;
        case AV_PIX_FMT_BAYER_BGGR16LE: pixel_format_string = @"AV_PIX_FMT_BAYER_BGGR16LE"; break;
        case AV_PIX_FMT_BAYER_BGGR16BE: pixel_format_string = @"AV_PIX_FMT_BAYER_BGGR16BE"; break;
        case AV_PIX_FMT_BAYER_RGGB16LE: pixel_format_string = @"AV_PIX_FMT_BAYER_RGGB16LE"; break;
        case AV_PIX_FMT_BAYER_RGGB16BE: pixel_format_string = @"AV_PIX_FMT_BAYER_RGGB16BE"; break;
        case AV_PIX_FMT_BAYER_GBRG16LE: pixel_format_string = @"AV_PIX_FMT_BAYER_GBRG16LE"; break;
        case AV_PIX_FMT_BAYER_GBRG16BE: pixel_format_string = @"AV_PIX_FMT_BAYER_GBRG16BE"; break;
        case AV_PIX_FMT_BAYER_GRBG16LE: pixel_format_string = @"AV_PIX_FMT_BAYER_GRBG16LE"; break;
        case AV_PIX_FMT_BAYER_GRBG16BE: pixel_format_string = @"AV_PIX_FMT_BAYER_GRBG16BE"; break;
        case AV_PIX_FMT_XVMC: pixel_format_string = @"AV_PIX_FMT_XVMC"; break;
        case AV_PIX_FMT_YUV440P10LE: pixel_format_string = @"AV_PIX_FMT_YUV440P10LE"; break;
        case AV_PIX_FMT_YUV440P10BE: pixel_format_string = @"AV_PIX_FMT_YUV440P10BE"; break;
        case AV_PIX_FMT_YUV440P12LE: pixel_format_string = @"AV_PIX_FMT_YUV440P12LE"; break;
        case AV_PIX_FMT_YUV440P12BE: pixel_format_string = @"AV_PIX_FMT_YUV440P12BE"; break;
        case AV_PIX_FMT_AYUV64LE: pixel_format_string = @"AV_PIX_FMT_AYUV64LE"; break;
        case AV_PIX_FMT_AYUV64BE: pixel_format_string = @"AV_PIX_FMT_AYUV64BE"; break;
        case AV_PIX_FMT_VIDEOTOOLBOX: pixel_format_string = @"AV_PIX_FMT_VIDEOTOOLBOX"; break;
        case AV_PIX_FMT_P010LE: pixel_format_string = @"AV_PIX_FMT_P010LE"; break;
        case AV_PIX_FMT_P010BE: pixel_format_string = @"AV_PIX_FMT_P010BE"; break;
        case AV_PIX_FMT_GBRAP12BE: pixel_format_string = @"AV_PIX_FMT_GBRAP12BE"; break;
        case AV_PIX_FMT_GBRAP12LE: pixel_format_string = @"AV_PIX_FMT_GBRAP12LE"; break;
        case AV_PIX_FMT_GBRAP10BE: pixel_format_string = @"AV_PIX_FMT_GBRAP10BE"; break;
        case AV_PIX_FMT_GBRAP10LE: pixel_format_string = @"AV_PIX_FMT_GBRAP10LE"; break;
        case AV_PIX_FMT_MEDIACODEC: pixel_format_string = @"AV_PIX_FMT_MEDIACODEC"; break;
        case AV_PIX_FMT_GRAY12BE: pixel_format_string = @"AV_PIX_FMT_GRAY12BE"; break;
        case AV_PIX_FMT_GRAY12LE: pixel_format_string = @"AV_PIX_FMT_GRAY12LE"; break;
        case AV_PIX_FMT_GRAY10BE: pixel_format_string = @"AV_PIX_FMT_GRAY10BE"; break;
        case AV_PIX_FMT_GRAY10LE: pixel_format_string = @"AV_PIX_FMT_GRAY10LE"; break;
        case AV_PIX_FMT_P016LE: pixel_format_string = @"AV_PIX_FMT_P016LE"; break;
        case AV_PIX_FMT_P016BE: pixel_format_string = @"AV_PIX_FMT_P016BE"; break;
        case AV_PIX_FMT_D3D11: pixel_format_string = @"AV_PIX_FMT_D3D11"; break;
        case AV_PIX_FMT_GRAY9BE: pixel_format_string = @"AV_PIX_FMT_GRAY9BE"; break;
        case AV_PIX_FMT_GRAY9LE: pixel_format_string = @"AV_PIX_FMT_GRAY9LE"; break;
        case AV_PIX_FMT_GBRPF32BE: pixel_format_string = @"AV_PIX_FMT_GBRPF32BE"; break;
        case AV_PIX_FMT_GBRPF32LE: pixel_format_string = @"AV_PIX_FMT_GBRPF32LE"; break;
        case AV_PIX_FMT_GBRAPF32BE: pixel_format_string = @"AV_PIX_FMT_GBRAPF32BE"; break;
        case AV_PIX_FMT_GBRAPF32LE: pixel_format_string = @"AV_PIX_FMT_GBRAPF32LE"; break;
        case AV_PIX_FMT_DRM_PRIME: pixel_format_string = @"AV_PIX_FMT_DRM_PRIME"; break;
        case AV_PIX_FMT_OPENCL: pixel_format_string = @"AV_PIX_FMT_OPENCL"; break;
        case AV_PIX_FMT_GRAY14BE: pixel_format_string = @"AV_PIX_FMT_GRAY14BE"; break;
        case AV_PIX_FMT_GRAY14LE: pixel_format_string = @"AV_PIX_FMT_GRAY14LE"; break;
        case AV_PIX_FMT_GRAYF32BE: pixel_format_string = @"AV_PIX_FMT_GRAYF32BE"; break;
        case AV_PIX_FMT_GRAYF32LE: pixel_format_string = @"AV_PIX_FMT_GRAYF32LE"; break;
        case AV_PIX_FMT_YUVA422P12BE: pixel_format_string = @"AV_PIX_FMT_YUVA422P12BE"; break;
        case AV_PIX_FMT_YUVA422P12LE: pixel_format_string = @"AV_PIX_FMT_YUVA422P12LE"; break;
        case AV_PIX_FMT_YUVA444P12BE: pixel_format_string = @"AV_PIX_FMT_YUVA444P12BE"; break;
        case AV_PIX_FMT_YUVA444P12LE: pixel_format_string = @"AV_PIX_FMT_YUVA444P12LE"; break;
        case AV_PIX_FMT_NV24: pixel_format_string = @"AV_PIX_FMT_NV24"; break;
        case AV_PIX_FMT_NV42: pixel_format_string = @"AV_PIX_FMT_NV42"; break;
        case AV_PIX_FMT_VULKAN: pixel_format_string = @"AV_PIX_FMT_VULKAN"; break;
        case AV_PIX_FMT_Y210BE: pixel_format_string = @"AV_PIX_FMT_Y210BE"; break;
        case AV_PIX_FMT_Y210LE: pixel_format_string = @"AV_PIX_FMT_Y210LE"; break;
        case AV_PIX_FMT_X2RGB10LE: pixel_format_string = @"AV_PIX_FMT_X2RGB10LE"; break;
        case AV_PIX_FMT_X2RGB10BE: pixel_format_string = @"AV_PIX_FMT_X2RGB10BE"; break;
        case AV_PIX_FMT_X2BGR10LE: pixel_format_string = @"AV_PIX_FMT_X2BGR10LE"; break;
        case AV_PIX_FMT_X2BGR10BE: pixel_format_string = @"AV_PIX_FMT_X2BGR10BE"; break;
        case AV_PIX_FMT_P210BE: pixel_format_string = @"AV_PIX_FMT_P210BE"; break;
        case AV_PIX_FMT_P210LE: pixel_format_string = @"AV_PIX_FMT_P210LE"; break;
        case AV_PIX_FMT_P410BE: pixel_format_string = @"AV_PIX_FMT_P410BE"; break;
        case AV_PIX_FMT_P410LE: pixel_format_string = @"AV_PIX_FMT_P410LE"; break;
        case AV_PIX_FMT_P216BE: pixel_format_string = @"AV_PIX_FMT_P216BE"; break;
        case AV_PIX_FMT_P216LE: pixel_format_string = @"AV_PIX_FMT_P216LE"; break;
        case AV_PIX_FMT_P416BE: pixel_format_string = @"AV_PIX_FMT_P416BE"; break;
        case AV_PIX_FMT_P416LE: pixel_format_string = @"AV_PIX_FMT_P416LE"; break;
        case AV_PIX_FMT_NB: pixel_format_string = @"AV_PIX_FMT_NB"; break;
        case AV_PIX_FMT_VUYA: pixel_format_string = @"AV_PIX_FMT_VUYA"; break;
        case AV_PIX_FMT_RGBAF16BE: pixel_format_string = @"AV_PIX_FMT_RGBAF16BE"; break;
        case AV_PIX_FMT_RGBAF16LE: pixel_format_string = @"AV_PIX_FMT_RGBAF16LE"; break;
        case AV_PIX_FMT_VUYX: pixel_format_string = @"AV_PIX_FMT_VUYX"; break;
        case AV_PIX_FMT_P012LE: pixel_format_string = @"AV_PIX_FMT_P012LE"; break;
        case AV_PIX_FMT_P012BE: pixel_format_string = @"AV_PIX_FMT_P012BE"; break;
        case AV_PIX_FMT_Y212BE: pixel_format_string = @"AV_PIX_FMT_Y212BE"; break;
        case AV_PIX_FMT_Y212LE: pixel_format_string = @"AV_PIX_FMT_Y212LE"; break;
        case AV_PIX_FMT_XV30BE: pixel_format_string = @"AV_PIX_FMT_XV30BE"; break;
        case AV_PIX_FMT_XV30LE: pixel_format_string = @"AV_PIX_FMT_XV30LE"; break;
        case AV_PIX_FMT_XV36BE: pixel_format_string = @"AV_PIX_FMT_XV36BE"; break;
        case AV_PIX_FMT_XV36LE: pixel_format_string = @"AV_PIX_FMT_XV36LE"; break;
        case AV_PIX_FMT_RGBF32BE: pixel_format_string = @"AV_PIX_FMT_RGBF32BE"; break;
        case AV_PIX_FMT_RGBF32LE: pixel_format_string = @"AV_PIX_FMT_RGBF32LE"; break;
        case AV_PIX_FMT_RGBAF32BE: pixel_format_string = @"AV_PIX_FMT_RGBAF32BE"; break;
        case AV_PIX_FMT_RGBAF32LE: pixel_format_string = @"AV_PIX_FMT_RGBAF32LE"; break;
    }
    return pixel_format_string;
}
+ (NSString *)av_picture_type:(AVFrame *)frame
{
    NSString *picture_type = @"";
    switch (frame->pict_type) {
            // < Undefined
        case AV_PICTURE_TYPE_NONE:
            picture_type = @"NONE";
            break;
            // < Intra
        case AV_PICTURE_TYPE_I:
            picture_type = @"I";
            break;
            // < Predicted
        case AV_PICTURE_TYPE_P:
            picture_type = @"P";
            break;
            // < Bi-dir predicted
        case AV_PICTURE_TYPE_B:
            picture_type = @"B";
            break;
            // < S(GMC)-VOP MPEG-4
        case AV_PICTURE_TYPE_S:
            picture_type = @"S";
            break;
            // < Switching Intra
        case AV_PICTURE_TYPE_SI:
            picture_type = @"SI";
            break;
            // < Switching Predicted
        case AV_PICTURE_TYPE_SP:
            picture_type = @"SP";
            break;
            // < BI type
        case AV_PICTURE_TYPE_BI:
            picture_type = @"BI";
            break;
        default:
            break;
    }
    return picture_type;
}
@end
